class HistoryGui extends BaseGui {

  static _cache := Map()

  __New(id, p) {
    super.__New('+Border') ; add 1px border
    this.id := id, this.savePath := p
    this.CreateTime(FileGetTime(this.savePath)).Border(1)
  }

  static FlushCache() => (
    HistoryGui._cache.Clear()
    SimpleLayout._cache.Clear()
    DynamicLayout.reset()
  )

  ; Adapt to the display position of the gui and do not overlap each other in a small number of tiles
  Show(w, h, id, *) {
    ; This method use only the left part of the screen
    local x, y
    if hit := HistoryGui._cache.Get(id, '') {
      x := hit.x, y := hit.y
    } else {
      DCon DynamicLayout.add({ w: w + 1, h: h + 1, id: id }), &x, &y ; 算上边框的2像素
      HistoryGui._cache.Set(id, { x: x, y: y })
    }

    super.Show('NA x' x ' y' y ' w' w ' h' h)
    WinSetTransparent(255, this)  ; lock
    this.RegisterEvent()
  }

  Destroy(*) {
    History.ReturnToPool(this.id)
    this.GetPos(&x, &y), HistoryGui._cache.Set(this.id, { x: x, y: y })
    super.Destroy()
  }
}

class DynamicLayout {

  static freeRects := [{ x: 80, y: 20, w: A_ScreenWidth, h: A_ScreenHeight }]

  static reset() {
    this.freeRects := [{ x: 80, y: 20, w: A_ScreenWidth, h: A_ScreenHeight }]
  }

  static add(item) {
    resetFreeRects := false, failCnt := 0
    loop {
      if failCnt > 1 { ; 始终放不下
        return [0, 0]
      }
      bestRectIndex := -1, bestRect := '', minWaste := 0x3f3f3f
      for rect in DynamicLayout.freeRects {
        if (rect.w >= item.w && rect.h >= item.h) {  ; FIXME bug here
          waste := (rect.w - item.w) * (rect.h - item.h)
          if (waste < minWaste)
            minWaste := waste, bestRectIndex := A_Index, bestRect := rect
        }
      }

      if (bestRect) {
        x := bestRect.x, y := bestRect.y
        _updateFreeRects(x, y, item.w, item.h)
        resetFreeRects := false
        return [x, y]
      } else {
        resetFreeRects := true, failCnt++
      }

      if (resetFreeRects) {
        DynamicLayout.reset()
      }
    } until !resetFreeRects


    _updateFreeRects(x, y, w, h) {
      newRects := []
      for rect in DynamicLayout.freeRects {
        if x + w <= rect.x || x >= rect.x + rect.w || y + h <= rect.y || y >= rect.y + rect.h
          newRects.push(rect)
        else {
          if y > rect.y
            newRects.push({ x: rect.x, y: rect.y, w: rect.w, h: y - rect.y })
          if y + h < rect.y + rect.h
            newRects.push({ x: rect.x, y: y + h, w: rect.w, h: rect.y + rect.h - (y + h) })
          if x > rect.x
            newRects.push({ x: rect.x, y: rect.y, w: x - rect.x, h: h })
          if x + w < rect.x + rect.w
            newRects.push({ x: x + w, y: rect.y, w: rect.x + rect.w - (x + w), h: h })
        }
      }
      DynamicLayout.freeRects := newRects.filter(rect => rect.w > 0 && rect.h > 0)
    }
  }

}

class SimpleLayout {
  ; 只使用左边屏幕，从上到下

  static _cache := Map()

  static add(item) {
    w := item.w, h := item.h, id := item.id
    if hit := SimpleLayout._cache.Get(id, '') {
      x := hit.x, y := hit.y
    } else {
      if SimpleLayout._cache.Has(id + 1) {
        point := SimpleLayout._cache.Get(id + 1)
        x := point.x
        y := point.y + point.h
        if y + h > A_ScreenHeight || x + w > A_ScreenWidth
          _getPoint(w, h, &x, &y)
      } else {
        _getPoint(w, h, &x, &y)
      }
      SimpleLayout._cache.Set(id, { x: x, y: y, h: h })
    }
    return [x, y]

    _getPoint(w, h, &nx, &ny) {
      x := 0, y := 0
      if w <= A_ScreenWidth - 80
        x := 80
      if h <= A_ScreenHeight - 20
        y := 20
      nx := x, ny := y
    }
  }
}

class BestFitLayout {
  ; 很慢
  static add(item) {

    static pages := [[]]
    containerW := A_ScreenWidth // 2, containerH := A_ScreenHeight // 2
    item.w //= 2, item.h //= 2
    r := placeItem(item)

    return r.map(v => v * 2)

    placeItem(_item) {
      while true {
        bestX := -1, bestY := -1, maxEmptySpace := -1, items := pages[A_Index]
        loop containerH - _item.h { ; 遍历每个可能的位置，找到最优的空隙
          y := A_Index
          loop containerW - _item.w {
            if (canPlaceItem(items, _item, A_Index, y)) {
              emptySpace := calculateEmptySpace(items, A_Index, y, _item) ; 计算当前空隙的空白空间大小
              if (emptySpace > maxEmptySpace)
                maxEmptySpace := emptySpace, bestX := A_Index, bestY := y
            }
          }
        }
        if (bestX != -1 && bestY != -1) { ; 如果找到合适位置，放置物品
          _item.x := bestX, _item.y := bestY
          pages[A_Index].push(_item)
          return [bestX, bestY]
        } else {
          pages.Push([])
        }
      }

      canPlaceItem(_, _item, x, y) {
        if (x + _item.w > containerW || y + _item.h > containerH) ; 检查是否超出容器边界
          return false
        for (v in _) { ; 检查是否与已有物品重叠
          if (x < v.x + v.w && x + _item.w > v.x && y < v.y + v.h && y + _item.h > v.y)
            return false
        }
        return true
      }

      calculateEmptySpace(_, x, y, _item) {
        space := 0
        for (v in _) { ; 计算与已放置物品的重叠区域
          if (x < v.x + v.w && x + _item.w > v.x && y < v.y + v.h && y + _item.h > v.y)
            space -= (min(x + _item.w, v.x + v.w) - max(x, v.x)) * (min(y + _item.h, v.y + v.h) - max(y, v.y))
        }
        return space
      }
    }


  }
}